package com.hou.serviceorder.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.Semaphore;

/**
 *  ApplicationContextAware实现类可以获得spring上下文
 *   间接获取ApplicationContext中的所有bean,向切面添加所有接口的配置的限流量
 */
@Component
public class InitApiLimit implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(RestController.class);
        beanMap.forEach((k,v)->{
            Class<?> controllerClass = v.getClass();
            //此处需要使用父类,因为开启代理之后,获取的是代理创建的子类,而子类无法获取父类的注解信息
            // (使用元注解@Inherited在自定义注解上可以使子类继承父类类上的注解,但是方法上的注解无法继承)
            //获取所有声明的方法
            Method[] allMethods = controllerClass.getSuperclass().getDeclaredMethods();
            for (Method method:allMethods){
                System.out.println(method.getName());
                //判断方法是否使用了限流注解
                if (method.isAnnotationPresent(ApiRateLimit.class)){
                    //获取配置的限流量,实际值可以动态获取,配置key,根据key从配置文件获取
                    int value = method.getAnnotation(ApiRateLimit.class).value();
                    String key = String.valueOf(value);
                    //key作为key.value为具体限流量,传递到切面的map中
                    ApiLimitAspect.semaphoreMap.put(key,new Semaphore(value));
                }
            }
            System.out.println("----信号量个数:"+ApiLimitAspect.semaphoreMap.size());
        });
    }
}
